<?php

declare(strict_types=1);

namespace App\Command;

use App\Model\Category;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Command\Annotation\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\DbConnection\Db;
use Hyperf\Support\Filesystem\Filesystem;
use function Hyperf\Support\env;

require_once(BASE_PATH . '/app/Libs/Helper.php');

/**
 * 批量导入模板文件数据和产品数据到mysql当中
 */
#[Command]
class SaveCateCommand extends HyperfCommand
{
    protected $logger;
    protected $config;

    public function __construct(StdoutLoggerInterface $logger, ConfigInterface $config)
    {
        $this->logger = $logger;
        $this->config = $config;

        // 定义命令行名称
        parent::__construct('save:cate');
    }

    public function configure()
    {
        parent::configure();
        $this->setDescription('批量保存分类');
    }

    public function handle()
    {
        $fs = new Filesystem();
        $dbname = env('DB_DATABASE', '');
        $modelCate = new Category();
        $tableCate = $modelCate::TABLE_NAME;
        $startTime = ceil(getMicrotime());

        // 1.检查路径
        $txtDir = BASE_PATH . '/storage/jkls_txt/';
        if (!$fs->isDirectory($txtDir)) {
            $this->logger->error('没有找到' . $txtDir . '这个目录');
            return \Hyperf\Command\Command::FAILURE;
        }

        // 2.获取产品文件
        $files = $fs->allFiles($txtDir);
        if (empty($files)) {
            $this->logger->error($txtDir . '目录下没有产品文件');
            return \Hyperf\Command\Command::FAILURE;
        }

        // 3.获取已经创建的表
        $res = Db::select("SELECT table_name FROM information_schema.tables WHERE table_schema = '{$dbname}' and table_name='{$tableCate}' limit 1");
        if (empty($res)) {
            $this->logger->error($txtDir . '请先导入分类表');
            return \Hyperf\Command\Command::FAILURE;
        }

        // 4.导入分类数据
        $cates1 = $cates2 = [];
        foreach ($files as $sk => $file) {
            $filename = $file->getFilename();
            $filepath = $file->getRealPath();
            if (!str_ends_with($filename, '.txt') || str_starts_with($filename, 'readme')) {
                continue;
            }
            $sj = $sk + 1;
            $this->line('  开始导入第' . $sj . '个-' . $filename);
            // 遍历并保存分类数据(至于分类的关键词数据，等后面再来统一更新)
            $fh = fopen($filepath, 'r');
            while (!feof($fh)) {
                $line = fgets($fh);
                if ($line !== false) {
                    $arr = explode('|', $line);
                    $logo = $arr[3] ?? '';
                    $cateArr = explode('-', $arr[0] ?? '');
                    $count = count($cateArr);
                    if (empty($cateArr)) {
                        continue;
                    }
                    if (!empty($cateArr)) {
                        if ($count === 4) {
                            if (!isset($cates1[$cateArr[3]])) {
                                $cates1[$cateArr[3]] = ['name' => $cateArr[3], 'logo' => $logo, 'is_parent' => 1, 'level' => 1, 'parent_id' => 0];
                            }
                            if (!isset($cates2[$cateArr[3]][$cateArr[1]])) {
                                $cates2[$cateArr[3]][$cateArr[1]] = ['name' => $cateArr[1], 'logo' => $logo, 'is_parent' => 0, 'level' => 2];
                            }
                        } elseif ($count === 2) {
                            if (!isset($cates1[$cateArr[1]])) {
                                $cates1[$cateArr[1]] = ['name' => $cateArr[1], 'logo' => $logo, 'is_parent' => 1, 'level' => 1];
                            }
                            // 给一个默认的二级分类
                            $cates2[$cateArr[1]]['その他'] = ['name' => 'その他', 'logo' => $logo, 'is_parent' => 0, 'level' => 2];
                        } elseif ($count === 6) {
                            if (!isset($cates1[$cateArr[5]])) {
                                $cates1[$cateArr[5]] = ['name' => $cateArr[5], 'logo' => $logo, 'is_parent' => 1, 'level' => 1];
                            }
                            if (!isset($cates2[$cateArr[5]][$cateArr[3]])) {
                                $cates2[$cateArr[5]][$cateArr[3]] = ['name' => $cateArr[3], 'logo' => $logo, 'is_parent' => 0, 'level' => 2];
                            }
                        }
                    }
                }
            }
            fclose($fh);
        }

        // 5.保存一级分类到表
        $this->line('开始保存一级分类数据');
        $cateNames1 = Db::table($tableCate)->where($modelCate::LEVEL, 1)->pluck($modelCate::ID, $modelCate::NAME)->toArray();
        foreach ($cates1 as $cname1 => &$item) {
            if (!empty($cateNames1) && isset($cateNames1[$cname1])) {
                $item['id'] = $cateNames1[$cname1];
            } else {
                $item['id'] = $modelCate->create([
                    $modelCate::NAME => $cname1,// 分类名称
                    $modelCate::LOGO => $item['logo'],// 图片
                    $modelCate::IS_PARENT => $item['is_parent'],// 是否父级
                    $modelCate::LEVEL => $item['level'],// 层级数，第一级=1，第二级=2以此类推
                ])->{$modelCate::ID};
            }
        }

        // 6.保存二级分类到表
        $this->line('开始保存二级分类数据');
        foreach ($cates2 as $cname1 => $items) {
            foreach ($items as $cname2 => &$item) {
                if (!isset($cates1[$cname1])) {
                    $this->logger->error("导入失败，一级分类{$cname1}保存到分类表失败");
                    return \Hyperf\Command\Command::FAILURE;
                }

                if (isset($cates1[$cname1]['id'])) {
                    $cid = Db::table($modelCate::TABLE_NAME)->where($modelCate::LEVEL, 2)->where($modelCate::NAME, $cname2)->where($modelCate::PARENT_ID, $cates1[$cname1]['id'])->first();
                    if (is_null($cid)) {
                        $cid = $modelCate->create([
                            $modelCate::NAME => $cname2,// 分类名称
                            $modelCate::LOGO => $item['logo'],// 图片
                            $modelCate::IS_PARENT => $item['is_parent'],// 是否父级
                            $modelCate::PARENT_ID => $cates1[$cname1]['id'],// 父级分类ID
                            $modelCate::PARENT_NAME => $cname1,// 父级分类名
                            $modelCate::LEVEL => $item['level'],// 层级数，第一级=1，第二级=2以此类推
                        ])->{$modelCate::ID};
                        $this->line('新增分类：' . $cid . ',name=' . $cname2);

                        if ($cates1[$cname1]['is_parent'] === 0) {
                            $cateFather = $modelCate::query()->find($cates1[$cname1]['id']);
                            $cateFather->{$modelCate::IS_PARENT} = 1;
                            $cateFather->save();
                            $cates1[$cname1]['is_parent'] = 1;
                        }
                    }
                    $cates2[$cname1][$cname2]['id'] = $cid;
                }
            }
        }

        // 检查与cate_words的差异，看关键词有少了哪些
        $cates = [];
        $cateNames1 = Db::table($tableCate)->where($modelCate::LEVEL, 1)->pluck($modelCate::ID, $modelCate::NAME)->toArray();
        foreach ($cateNames1 as $cname1 => $cid1) {
            $cateNames2 = Db::table($tableCate)->where($modelCate::LEVEL, 2)->where($modelCate::PARENT_ID, $cid1)->pluck($modelCate::NAME)->toArray();
            if (!empty($cateNames2)) {
                $cname1 = str_replace('/', '-', $cname1);
                foreach ($cateNames2 as $cname2) {
                    $cname2 = str_replace('/', '-', $cname2);
                    $cates[$cname1][] = $cname2;
                }
            }
        }

        $cateWordDir = BASE_PATH . '/storage/cate_words/';
        if ($fs->isDirectory($cateWordDir)) {
            $files = $fs->allFiles($cateWordDir);
            if (!empty($files)) {
                $arr = [];
                foreach ($files as $sk => $file) {
                    $filepath = $file->getRealPath();
                    $filename = $file->getFilename();
                    if (!str_ends_with($filename, '.txt')) {
                        continue;
                    }

                    $pos = strpos($filepath, 'cate_words');
                    if ($pos === false) {
                        return '';
                    }
                    $filepath = str_replace('.txt', '', mb_substr($filepath, $pos + 11));
                    $pathArr = explode(DIRECTORY_SEPARATOR, $filepath);
                    $catename1 = $pathArr[0];
                    if (isset($pathArr[1])) {
                        $catename2 = $pathArr[1];
                        $arr[$catename1][] = $catename2;
                    }
                }
                $e1 = $e2 = [];
                foreach ($cates as $cname1 => $names2) {
                    foreach ($names2 as $cname2) {
                        if (!isset($arr[$cname1])) {
                            if (empty($e1) || (!empty($e1) && !in_array($cname1, $e1))) {
                                $e1[] = $cname1;
                            }
                        } else {
                            if (!in_array($cname2, $arr[$cname1])) {
                                if (empty($e2) || (isset($e2[$cname1]) && !in_array($cname2, $e2[$cname1]))) {
                                    $e2[$cname1][] = $cname2;
                                }
                            }
                        }
                    }
                }
                if (!empty($e1)) {
                    foreach ($e1 as $name1) {
                        $this->error('一级分类在cate_words中不存在,name1=' . $name1);
                    }
                }
                if (!empty($e2)) {
                    foreach ($e2 as $n1 => $items) {
                        foreach ($items as $name2) {
                            $this->error('二级分类在cate_words中不存在,name1=' . $n1 . ',name2=' . $name2);
                        }
                    }
                }
            }
        }

        $endTime = ceil(getMicrotime());
        $huafei = $endTime - $startTime;

        $this->line('分类已经全部入库完成，共花费' . $huafei . '秒，程序退出');
        return \Hyperf\Command\Command::SUCCESS;
    }
}
